home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / SOURCES / TRAY.C < prev    next >
C/C++ Source or Header  |  1992-03-12  |  54KB  |  2,190 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Tray implementation.
  25.  */
  26.  
  27. #include <InterViews/canvas.h>
  28. #include <InterViews/painter.h>
  29. #include <InterViews/shape.h>
  30. #include <InterViews/tray.h>
  31.  
  32. inline float abs (float f) { return (f < 0) ? -f : f; }
  33.  
  34. /*************************************************************************/
  35.  
  36. class TElement {
  37. public:
  38.     TElement(Interactor*);
  39.     TElement(TGlue*);
  40.     TElement();
  41.     ~TElement();
  42.  
  43.     float pos, sigma;            /* ultimate values */
  44.     float nat, stretch, shrink;
  45.     boolean combinable;            /* false for tray elements when calcing */
  46.                     /* shape of tray having no background */
  47.     boolean leftBotHalf;        /* true if represents left/bottom of a */
  48.                     /* pair of elems modelling an interactor */
  49.     Interactor* owner;
  50.     TGlue* tglue;
  51.  
  52.     void HSetShape();
  53.     void VSetShape();
  54.     TElement* Series(TElement*);    /* series combination */
  55.     TElement* Parallel(TElement*);    /* parallel combination */
  56.     void Reverse();
  57.     void Limit();
  58. };
  59.  
  60. TElement::TElement (Interactor* i) {
  61.     owner = i;
  62.     tglue = nil;
  63.     pos = sigma = 0;
  64. }
  65.  
  66. TElement::TElement (TGlue* tg) {
  67.     owner = nil;
  68.     tglue = tg;
  69.     pos = sigma = 0;
  70. }
  71.  
  72. TElement::TElement () {
  73.     owner = nil;
  74.     tglue = nil;
  75.     pos = sigma = 0;
  76. }
  77.  
  78. TElement::~TElement () {
  79.     delete tglue;
  80. }
  81.  
  82. void TElement::HSetShape () {
  83.     Shape* s;
  84.  
  85.     if (tglue == nil) {
  86.     s = owner->GetShape();
  87.     nat = float(s->width)/2;
  88.     stretch = float(s->hstretch)/2;
  89.     shrink = float(s->hshrink)/2;
  90.     } else {
  91.     s = tglue->GetShape();
  92.     nat = s->width;
  93.     stretch = s->hstretch;
  94.     shrink = s->hshrink;
  95.     }
  96. }
  97.  
  98. void TElement::VSetShape () {
  99.     Shape* s;
  100.  
  101.     if (tglue == nil) {
  102.     s = owner->GetShape();
  103.     nat = float(s->height)/2;
  104.     stretch = float(s->vstretch)/2;
  105.     shrink = float(s->vshrink)/2;
  106.     } else {
  107.     s = tglue->GetShape();
  108.     nat = s->height;
  109.     stretch = s->vstretch;
  110.     shrink = s->vshrink;
  111.     }
  112. }
  113.  
  114. TElement* TElement::Series (TElement* e) {
  115.     TElement* combo = new TElement;
  116.     register TElement* c;
  117.     
  118.     combo->combinable = combinable || e->combinable;
  119.     
  120.     if (combinable && e->combinable) {
  121.     combo->nat = nat + e->nat;
  122.     combo->stretch = stretch + e->stretch;
  123.     combo->shrink = shrink + e->shrink;
  124.  
  125.     } else if (combo->combinable) {
  126.     c = combinable ? this : e;
  127.     combo->nat = c->nat;
  128.     combo->stretch = c->stretch;
  129.     combo->shrink = c->shrink;
  130.     }
  131.     
  132.     return combo;
  133. }
  134.  
  135. TElement* TElement::Parallel (TElement* e) {
  136.     TElement* combo = new TElement;
  137.     register TElement* c;
  138.     float emin, emax;
  139.     
  140.     emin = max(nat - shrink, e->nat - e->shrink);
  141.     emax = min(nat + stretch, e->nat + e->stretch);
  142.     combo->combinable = combinable || e->combinable;
  143.  
  144.     if (combinable && e->combinable) {
  145.     combo->nat = max(nat, e->nat);
  146.     combo->stretch = max(0, int(emax - combo->nat));
  147.     combo->shrink = max(0, int(combo->nat - emin));
  148.     } else if (combo->combinable) {
  149.     c = combinable ? this : e;
  150.     combo->nat = c->nat;
  151.     combo->stretch = c->stretch;
  152.     combo->shrink = c->shrink;
  153.     }
  154.     return combo;
  155. }
  156.  
  157. void TElement::Reverse () {
  158.     float tmp;
  159.  
  160.     nat = -nat;
  161.     tmp = stretch;
  162.     stretch = shrink;
  163.     shrink = tmp;
  164.     sigma = -sigma;
  165.     pos -= nat + sigma + 1;
  166. }
  167.  
  168. void TElement::Limit () {
  169.     sigma = min(max(-shrink, sigma), stretch);
  170. }
  171.  
  172. /*************************************************************************/
  173.  
  174. class TList {
  175. public:
  176.     ~TList();
  177. protected:
  178.     TList(void* = nil);
  179.  
  180.     void Append(TList*);
  181.     void Prepend(TList*);
  182.     void Remove(TList*);
  183.     TList* First();
  184.     TList* Last();
  185.     TList* End();
  186.     TList* Next();
  187.     TList* Prev();
  188.     boolean Empty();
  189.  
  190.     void SetContents(void*);
  191.     void* GetContents();
  192.     void Delete(void*);
  193.     TList* Find(void*);
  194. private:
  195.     void* object;
  196.     TList* next;
  197.     TList* prev;
  198. };
  199.  
  200. inline TList::TList (void* o) { next = this; prev = this; object = o; }
  201. inline TList* TList::First () { return next; }
  202. inline TList* TList::Last () { return prev; }
  203. inline TList* TList::End () { return this; }
  204. inline TList* TList::Next () { return next; }
  205. inline TList* TList::Prev () { return prev; }
  206. inline boolean TList::Empty () { return next == this; }
  207. inline void TList::SetContents (void *o) { object = o; }
  208. inline void* TList::GetContents () { return object; }
  209.  
  210. inline void TList::Append (TList* e) {
  211.     prev->next = e;
  212.     e->prev = prev;
  213.     e->next = this;
  214.     prev = e;
  215. }
  216.  
  217. inline void TList::Prepend (TList* e) {
  218.     next->prev = e;
  219.     e->prev = this;
  220.     e->next = next;
  221.     next = e;
  222. }
  223.  
  224. inline void TList::Remove (TList* e) {
  225.     e->prev->next = e->next;
  226.     e->next->prev = e->prev;
  227.     e->next = e->prev = e;
  228. }
  229.  
  230. TList::~TList () {
  231.     TList* e;
  232.     
  233.     if (!Empty()) {
  234.     e = First();
  235.     Remove(this);
  236.     delete e;
  237.     }
  238. }
  239.  
  240. void TList::Delete (void* o) {
  241.     register TList* e;
  242.  
  243.     e = Find(o);
  244.     if (e != nil) {
  245.     Remove(e);
  246.     delete e;
  247.     }
  248. }
  249.  
  250. TList* TList::Find (void* o) {
  251.     register TList* e;
  252.  
  253.     for (e = next; e != this; e = e->next) {
  254.     if (e->GetContents() == o) {
  255.         return e;
  256.     }
  257.     }
  258.     return nil;
  259. }
  260.  
  261. /*************************************************************************/
  262.  
  263. class TElementList : public TList {
  264. public:
  265.     TElementList(TElement* = nil);
  266.     TElementList* Copy();
  267.  
  268.     boolean Includes(TElement*);
  269.     boolean Includes(Interactor*, TElement*&);
  270.  
  271.     void Append(TElementList*);
  272.     void Remove(TElementList*);
  273.     TElementList* First();
  274.     TElementList* End();
  275.     TElementList* Next();
  276.     void Delete(TElement*);
  277.     boolean Empty();
  278.     boolean OnlyOne();
  279.     boolean OnlyTwo();
  280.     TElement* GetElem();
  281. };
  282.  
  283. inline TElement* TElementList::GetElem () { return (TElement*) GetContents();}
  284. inline void TElementList::Append (TElementList* el) { TList::Append(el); }
  285. inline void TElementList::Remove (TElementList* el) { TList::Remove(el); }
  286. inline void TElementList::Delete (TElement* o) { TList::Delete(o); }
  287. inline boolean TElementList::Includes (TElement* e) { return Find(e) != nil; }
  288. inline TElementList* TElementList::First () 
  289.     { return (TElementList*) TList::First(); }
  290. inline TElementList* TElementList::End ()
  291.     { return (TElementList*) TList::End(); }
  292. inline TElementList* TElementList::Next () 
  293.     { return (TElementList*) TList::Next(); }
  294. inline boolean TElementList::Empty () { return TList::Empty(); }
  295. inline boolean TElementList::OnlyOne () { return !Empty() && First()==Last(); }
  296. inline boolean TElementList::OnlyTwo ()
  297.     { return !Empty() && !OnlyOne() && First()->Next() == Last(); }
  298.  
  299. TElementList::TElementList (TElement* o) : (o) { }
  300.  
  301. TElementList* TElementList::Copy () {
  302.     register TElementList* t;
  303.     TElementList* newlist = new TElementList;
  304.     
  305.     for (t = First(); t != End(); t = t->Next()) {
  306.     newlist->Append(new TElementList(t->GetElem()));
  307.     }
  308.     return newlist;
  309. }
  310.  
  311. boolean TElementList::Includes (Interactor* i, TElement*& e) {
  312.     register TElementList* t;
  313.  
  314.     for (t = First(); t != End(); t = t->Next()) {
  315.     e = t->GetElem();
  316.     if (e->owner == i) {
  317.         return true;
  318.     }
  319.     }
  320.     return false;
  321. }
  322.  
  323. /*************************************************************************/
  324.  
  325. class TTermination {
  326. public:
  327.     Alignment alignment, toAttached;
  328.     TElement* dangling, *attached;
  329.  
  330.     TTermination(Alignment, TElement*, Alignment, TElement*);
  331. };
  332.  
  333. TTermination::TTermination (
  334.     Alignment a, TElement* d, Alignment to, TElement* e
  335. ) {
  336.     alignment = a;
  337.     dangling = d;
  338.     toAttached = to;
  339.     attached = e;
  340. }
  341.  
  342. /*************************************************************************/
  343.  
  344. class TLoop {
  345. public:
  346.     Alignment toAttached;
  347.     TElement* looped, *attached;
  348.     
  349.     TLoop(TElement*, Alignment, TElement*);
  350. };
  351.  
  352. TLoop::TLoop (TElement* l, Alignment to, TElement* e) {
  353.     looped = l;
  354.     toAttached = to;
  355.     attached = e;
  356. }    
  357.  
  358. /*************************************************************************/
  359.  
  360. class TNode {
  361.     friend class TNodeList;
  362. public:
  363.     TNode(TElementList* = nil, TElementList* = nil);
  364.     TNode(Alignment, TElement*, Alignment = BottomLeft, TElement* = nil);
  365.     ~TNode();
  366.     TNode* Copy();
  367.     void DeleteElements();
  368.     
  369.     void Merge(TNode*);
  370.     void Exclude(TElement*);
  371.     boolean Includes(TElement*);
  372.     boolean Includes(Alignment&, TElement*);
  373.     boolean Overlaps(TNode*);
  374.     boolean Empty();
  375.     boolean Degenerate(TElement*&);
  376.     boolean Degenerate(Alignment&, TElement*&);
  377.     boolean Series(TElement*&, TElement*&);
  378.     boolean Stub(TElement*&);
  379.     boolean Loop(TElement*&);
  380.  
  381.     void SetPosition(float);
  382.     float GetPosition();
  383. private:
  384.     TElementList* lbElems, *rtElems;
  385.     float position;
  386.  
  387.     TElementList* LeftBottomElements();
  388.     TElementList* RightTopElements();
  389.     void DeleteElements(TElementList*);
  390. };
  391.  
  392. inline boolean TNode::Includes (TElement* e) 
  393.     { Alignment dummy; return Includes(dummy, e); }
  394. inline boolean TNode::Empty () { return lbElems->Empty() && rtElems->Empty(); }
  395. inline void TNode::SetPosition (float p) { position = p; }
  396. inline float TNode::GetPosition () { return position; }
  397. inline TElementList* TNode::LeftBottomElements () { return lbElems; }
  398. inline TElementList* TNode::RightTopElements () { return rtElems; }
  399.  
  400. TNode::TNode (TElementList* l1, TElementList* l2) {
  401.     lbElems = l1;
  402.     rtElems = l2;
  403.     position = 0;
  404. }
  405.     
  406. TNode::TNode (Alignment a1, TElement* e1, Alignment a2, TElement* e2) {
  407.     lbElems = new TElementList;
  408.     rtElems = new TElementList;
  409.  
  410.     if (a1 == BottomLeft) {
  411.     rtElems->Append(new TElementList(e1));
  412.     } else {
  413.     lbElems->Append(new TElementList(e1));
  414.     }
  415.     if (e2 != nil) {
  416.     if (a2 == BottomLeft) {
  417.         rtElems->Append(new TElementList(e2));
  418.     } else {
  419.         lbElems->Append(new TElementList(e2));
  420.     }
  421.     position = 0;
  422.     }
  423. }
  424.  
  425. TNode::~TNode () { delete lbElems; delete rtElems; }
  426.  
  427. void TNode::DeleteElements () {
  428.     register TElementList* t;
  429.     
  430.     for (t = lbElems->First(); t != lbElems->End(); t = t->Next()) {
  431.         rtElems->Delete(t->GetElem());
  432.     }
  433.     DeleteElements(lbElems);
  434.     DeleteElements(rtElems);
  435. }
  436.  
  437. void TNode::DeleteElements (TElementList* elems) {
  438.     register TElementList* t;
  439.  
  440.     for (t = elems->First(); t != elems->End(); t = t->Next()) {
  441.         delete t->GetElem();
  442.     }
  443. }
  444.  
  445. TNode* TNode::Copy () { 
  446.     TNode* node = new TNode(lbElems->Copy(), rtElems->Copy());
  447.     node->SetPosition(GetPosition());
  448.     return node;
  449. }
  450.  
  451. void TNode::Merge (TNode* n) {
  452.     register TElementList* nelems, *next;
  453.     TElementList* cur;
  454.     
  455.     nelems = n->lbElems;
  456.     for (cur = nelems->First(); cur != nelems->End(); cur = next) {
  457.     next = cur->Next();
  458.     nelems->Remove(cur);
  459.     if (lbElems->Includes(cur->GetElem())) {
  460.             delete cur;
  461.         } else {
  462.         lbElems->Append(cur);
  463.     }
  464.     }
  465.     nelems = n->rtElems;
  466.     for (cur = nelems->First(); cur != nelems->End(); cur = next) {
  467.     next = cur->Next();
  468.     nelems->Remove(cur);
  469.     if (rtElems->Includes(cur->GetElem())) {
  470.             delete cur;
  471.         } else {
  472.         rtElems->Append(cur);
  473.     }
  474.     }
  475. }
  476.  
  477. void TNode::Exclude (TElement* e) {
  478.     lbElems->Delete(e);
  479.     rtElems->Delete(e);
  480. }
  481.  
  482. boolean TNode::Includes (Alignment& a, TElement* e) {
  483.     if (lbElems->Includes(e)) {
  484.     a = TopRight;
  485.     return true;
  486.     } else if (rtElems->Includes(e)) {
  487.     a = BottomLeft;
  488.     return true;
  489.     };
  490.     return false;
  491. }
  492.  
  493. boolean TNode::Overlaps (TNode* n) {
  494.     register TElementList* nelems;
  495.     register TElementList* cur;
  496.     
  497.     nelems = n->lbElems;
  498.     for (cur = nelems->First(); cur != nelems->End(); cur = cur->Next()) {
  499.     if (lbElems->Includes(cur->GetElem())) {
  500.         return true;
  501.     }
  502.     }
  503.     nelems = n->rtElems;
  504.     for (cur = nelems->First(); cur != nelems->End(); cur = cur->Next()) {
  505.     if (rtElems->Includes(cur->GetElem())) {
  506.         return true;
  507.     }
  508.     }
  509.     return false;
  510. }
  511.  
  512. boolean TNode::Degenerate (TElement*& e) {
  513.     Alignment dummy; 
  514.  
  515.     return Degenerate(dummy, e);
  516. }
  517.  
  518. boolean TNode::Degenerate (Alignment& a, TElement*& e) {
  519.     if (!lbElems->Empty() && rtElems->Empty()) {
  520.     if (lbElems->OnlyOne()) {
  521.         e = lbElems->First()->GetElem();
  522.         a = TopRight;
  523.         return true;
  524.     }
  525.     } else if (lbElems->Empty() && !rtElems->Empty()) {
  526.     if (rtElems->OnlyOne()) {
  527.         e = rtElems->First()->GetElem();
  528.         a = BottomLeft;
  529.         return true;
  530.     }
  531.     }
  532.     return false;
  533. }
  534.  
  535. boolean TNode::Series (TElement*& e1, TElement*& e2) {
  536.     if (
  537.     !lbElems->Empty() && !rtElems->Empty() &&
  538.     lbElems->OnlyOne() && rtElems->OnlyOne()
  539.     ) {
  540.     e1 = lbElems->First()->GetElem();
  541.     e2 = rtElems->First()->GetElem();
  542.     if (e1 != e2) {
  543.         return true;
  544.     }
  545.     }
  546.     return false;
  547. }
  548.  
  549. boolean TNode::Stub (TElement*& e) {
  550.     if (lbElems->OnlyTwo() && rtElems->Empty()) {
  551.     e = lbElems->First()->GetElem();
  552.     return true;
  553.  
  554.     } else if (lbElems->Empty() && rtElems->OnlyTwo()) {
  555.     e = rtElems->First()->GetElem();
  556.     return true;
  557.     }
  558.     return false;
  559. }
  560.  
  561. boolean TNode::Loop (TElement*& e) {
  562.     register TElementList* cur;
  563.     
  564.     for (cur = lbElems->First(); cur != lbElems->End(); cur = cur->Next()) {
  565.     e = cur->GetElem();
  566.     if (rtElems->Includes(e)) {
  567.         return true;
  568.     }
  569.     }
  570.     return false;
  571. }
  572.  
  573. /*************************************************************************/
  574.  
  575. class TNodeList : public TList {
  576. public:
  577.     TNodeList(TNode* = nil);
  578.     TNodeList* Copy();
  579.  
  580.     void Include(Alignment, TElement*, Alignment = BottomLeft, TElement* =nil);
  581.     void Exclude(TElement*);
  582.     boolean Includes(TNode*);
  583.     void Nodes(TElement*, TNode*&, TNode*&);
  584.     TNode* Node(Alignment, TElement*);
  585.     TNode* OtherNode(TElement*, TNode*);
  586.     void AddMissingNodes(TElement*);
  587.  
  588.     void Append(TNodeList*);
  589.     void Remove(TNodeList*);
  590.     TNodeList* First();
  591.     TNodeList* End();
  592.     TNodeList* Next();
  593.     TNodeList* Last();
  594.     void Delete(TNode*);
  595.     boolean Empty();
  596.     boolean OnlyOne();
  597.     TNode* GetNode();
  598.     
  599.     boolean Degenerate(TElement*&);
  600.     boolean FoundTermination(TTermination*&, TNode*, TNode*);
  601.     boolean FoundSeries(TElement*&, TElement*&, TNode*, TNode*);
  602.     boolean FoundStub(TElement*&);
  603.     boolean FoundParallel(TElement*&, TElement*&);
  604.     boolean FoundCrossover(TElement*&);
  605.     boolean FoundLoop(TLoop*&);
  606.     void Reverse(TElement*);
  607.     
  608.     void RemoveTermination(TTermination*);
  609.     void RemoveSeries(TElement*, TElement*, TElement*);
  610.     void RemoveParallel(TElement*, TElement*, TElement*);
  611.     void RemoveLoop(TLoop*);
  612.  
  613.     void ReplaceTermination(TTermination*);
  614.     void ReplaceSeries(TElement*, TElement*, TElement*);
  615.     void ReplaceParallel(TElement*, TElement*, TElement*);
  616.     void ReplaceLoop(TLoop*);
  617.  
  618.     void ApplyToTermination(TTermination*);
  619.     void ApplyToSeries(TElement*, TElement*, TElement*);
  620.     void ApplyToParallel(TElement*, TElement*, TElement*);
  621.     void ApplyToLoop(TLoop*);
  622.  
  623.     void FindElements(Interactor*, TElement*&, TElement*&);
  624.     void FindElement(TGlue*, TElement*&);
  625. private:
  626.     boolean FoundParallel(TNode*, TElement*&, TElement*&);
  627.     boolean FoundParallel(TElementList*, TNode*, TElement*&, TElement*&);
  628.     boolean FoundCrossover(TNode*, TElement*&);
  629.     void FindElements(TElementList*, Interactor*, TElement*&, TElement*&);
  630.     void FindElement(TElementList*, TGlue*, TElement*&);
  631.     Alignment Inverse(Alignment);
  632.     void GetElemOtherThan(TElement*, TNode*, Alignment&, TElement*&);
  633. };
  634.  
  635. inline boolean TNodeList::Includes (TNode* t) { return TList::Find(t) != nil; }
  636. inline TNode* TNodeList::GetNode () { return (TNode*) GetContents(); }
  637. inline boolean TNodeList::FoundParallel (
  638.     TNode* n, TElement*& e1, TElement*& e2
  639. ) {
  640.     return    
  641.     FoundParallel(n->LeftBottomElements(), n, e1, e2) ||
  642.     FoundParallel(n->RightTopElements(), n, e1, e2);
  643. }
  644. inline void TNodeList::Append (TNodeList* t) { TList::Append(t); }
  645. inline void TNodeList::Remove (TNodeList* t) { TList::Remove(t); }
  646. inline void TNodeList::Delete (TNode* o) { TList::Delete(o); }
  647. inline TNodeList* TNodeList::First () { return (TNodeList*) TList::First(); }
  648. inline TNodeList* TNodeList::End () { return (TNodeList*) TList::End(); }
  649. inline TNodeList* TNodeList::Next () { return (TNodeList*) TList::Next(); }
  650. inline TNodeList* TNodeList::Last () { return (TNodeList*) TList::Last(); }
  651. inline boolean TNodeList::Empty () { return TList::Empty(); }
  652. inline boolean TNodeList::OnlyOne () { return !Empty() && First() == Last(); }
  653. inline Alignment TNodeList::Inverse (Alignment a)
  654.     { return (a == BottomLeft) ? TopRight : BottomLeft; }
  655.  
  656. TNodeList::TNodeList (TNode* o) : (o) { }
  657.  
  658. TNodeList* TNodeList::Copy () {
  659.     register TNodeList* t;
  660.     TNodeList* newlist = new TNodeList;
  661.     TNode* node;
  662.     
  663.     for (t = First(); t != End(); t = t->Next()) {
  664.     node = t->GetNode();
  665.     newlist->Append(new TNodeList(node->Copy()));
  666.     }
  667.     return newlist;
  668. }
  669.  
  670. void TNodeList::Include (
  671.     Alignment a1, TElement* e1, Alignment a2, TElement* e2
  672. ) {
  673.     register TNodeList* t;
  674.     TNode pass1(a1, e1, a2, e2);
  675.     TNode* node, *pass2;
  676.     
  677.     for (t = First(); t != End(); t = t->Next()) {
  678.     node = t->GetNode();
  679.     if (node->Overlaps(&pass1)) {
  680.         node->Merge(&pass1);
  681.         pass2 = node;
  682.         break;
  683.     }
  684.     }
  685.     if (t == End()) {
  686.     Append(new TNodeList(pass1.Copy()));
  687.  
  688.     } else {
  689.     for (t = First(); t != End(); t = t->Next()) {
  690.         node = t->GetNode();
  691.         if (node != pass2 && node->Overlaps(pass2)) {
  692.         node->Merge(pass2);
  693.         Delete(pass2);
  694.         delete pass2;
  695.         break;
  696.         }
  697.     }
  698.     }
  699. }
  700.  
  701. void TNodeList::Exclude (TElement* e) {
  702.     register TNodeList* t, *next;
  703.     TNode* node;
  704.     int n = 0;
  705.     
  706.     for (t = First(); t != End() && n <= 1; t = next) {
  707.     next = t->Next();
  708.     node = t->GetNode();
  709.     if (node->Includes(e)) {
  710.         ++n;
  711.         node->Exclude(e);
  712.         if (node->Empty()) {
  713.         Remove(t);
  714.         delete t;
  715.         }
  716.     }
  717.     }
  718. }
  719.  
  720. boolean TNodeList::Degenerate (TElement*& e) {
  721.     TElement* alt;
  722.     TNode* nfirst = First()->GetNode();
  723.     TNode* nlast = Last()->GetNode();
  724.  
  725.     return
  726.     First()->Next() == Last() &&
  727.     nfirst->Degenerate(e) && nlast->Degenerate(alt) &&
  728.     e == alt;
  729. }
  730.  
  731. boolean TNodeList::FoundTermination (
  732.     TTermination*& term, TNode* lbMagic, TNode* rtMagic
  733. ) {
  734.     register TNodeList* t;
  735.     TElement* dangling, *attached;
  736.     Alignment a, toAttached;
  737.     TNode* degenTest, *attachment;
  738.     
  739.     for (t = First(); t != End(); t = t->Next()) {
  740.     degenTest = t->GetNode();
  741.  
  742.     if (
  743.         degenTest != lbMagic && degenTest != rtMagic &&
  744.         degenTest->Degenerate(a, dangling)
  745.     ) {
  746.         attachment = OtherNode(dangling, degenTest);
  747.             GetElemOtherThan(dangling, attachment, toAttached, attached);
  748.             if (attached != nil) {
  749.                 term = new TTermination(a, dangling, toAttached, attached);
  750.                 return true;
  751.             }
  752.     }
  753.     }
  754.     return false;
  755. }
  756.  
  757. boolean TNodeList::FoundSeries (
  758.     TElement*& e1, TElement*& e2, TNode* lbMagic, TNode* rtMagic
  759. ) {
  760.     register TNodeList* t;
  761.     TNode* node;
  762.     
  763.     for (t = First(); t != End(); t = t->Next()) {
  764.     node = t->GetNode();
  765.     if (node != lbMagic && node != rtMagic && node->Series(e1, e2)) {
  766.         return true;
  767.     }
  768.     }
  769.     return false;
  770. }
  771.  
  772. boolean TNodeList::FoundStub (TElement*& e) {
  773.     register TNodeList* t;
  774.     TNode* node;
  775.     
  776.     for (t = First(); t != End(); t = t->Next()) {
  777.     node = t->GetNode();
  778.     if (node->Stub(e)) {
  779.         return true;
  780.     }
  781.     }
  782.     return false;
  783. }
  784.  
  785. boolean TNodeList::FoundParallel (TElement*& e1, TElement*& e2) {
  786.     register TNodeList* t;
  787.     TNode* node;
  788.     
  789.     for (t = First(); t != End(); t = t->Next()) {
  790.     node = t->GetNode();
  791.     if (FoundParallel(node, e1, e2)) {
  792.         return true;
  793.     }
  794.     }
  795.     return false;
  796. }
  797.  
  798. boolean TNodeList::FoundParallel (
  799.     TElementList* elems, TNode* n, TElement*& e1, TElement*& e2
  800. ) {
  801.     register TElementList* cur, *test;
  802.     TNode* ncur, *ntest;
  803.     
  804.     for (cur = elems->First(); cur != elems->End(); cur = cur->Next()) {
  805.     e1 = cur->GetElem();
  806.     ncur = OtherNode(e1, n);
  807.  
  808.     if (ncur != nil) {
  809.         for (
  810.         test = cur->Next();
  811.         test != elems->End();
  812.         test = test->Next()
  813.         ) {
  814.         e2 = test->GetElem();
  815.         ntest = OtherNode(e2, n);
  816.         if (ntest == ncur) {
  817.             return true;
  818.         }
  819.         }
  820.     }
  821.     }
  822.     return false;
  823. }
  824.  
  825. boolean TNodeList::FoundCrossover (TElement*& e) {
  826.     register TNodeList* t;
  827.     TNode* node;
  828.     
  829.     for (t = First(); t != End(); t = t->Next()) {
  830.     node = t->GetNode();
  831.     if (FoundCrossover(node, e)) {
  832.         return true;
  833.     }
  834.     }
  835.     return false;
  836. }
  837.  
  838. boolean TNodeList::FoundLoop (TLoop*& loop) {
  839.     register TNodeList* t;
  840.     TElement* looped, *attached;
  841.     Alignment toAttached;
  842.     TNode* loopTest;
  843.     
  844.     for (t = First(); t != End(); t = t->Next()) {
  845.     loopTest = t->GetNode();
  846.     if (loopTest->Loop(looped)) {
  847.         GetElemOtherThan(looped, loopTest, toAttached, attached);
  848.         loop = new TLoop(looped, toAttached, attached);
  849.         return true;
  850.     }
  851.     }
  852.     return false;
  853. }
  854.  
  855. boolean TNodeList::FoundCrossover (TNode* n, TElement*& e1) {
  856.     TElementList* lbElems, *rtElems, *cur, *test;
  857.     TElement* e2;
  858.     TNode* ncur, *ntest;
  859.     
  860.     lbElems = n->LeftBottomElements();
  861.     rtElems = n->RightTopElements();
  862.     
  863.     for (cur = lbElems->First(); cur != lbElems->End(); cur = cur->Next()) {
  864.     e1 = cur->GetElem();
  865.     ncur = OtherNode(e1, n);
  866.     
  867.     if (ncur != nil) {
  868.         for (
  869.         test = rtElems->First(); 
  870.         test != rtElems->End(); 
  871.         test = test->Next()
  872.         ) {
  873.         e2 = test->GetElem();
  874.         ntest = OtherNode(e2, n);
  875.         if (ntest == ncur) {
  876.             return true;
  877.         }
  878.         }
  879.     }
  880.     }
  881.     return false;
  882. }
  883.  
  884. TNode* TNodeList::OtherNode (TElement* e, TNode* n) {
  885.     register TNodeList* t;
  886.     TNode* ntest;
  887.     
  888.     for (t = First(); t != End(); t = t->Next()) {
  889.     ntest = t->GetNode();
  890.     if (ntest != n && ntest->Includes(e)) {
  891.         return ntest;
  892.     }
  893.     }
  894.     return nil;
  895. }
  896.  
  897. void TNodeList::RemoveTermination (TTermination* t) {
  898.     TNode* degen, *attachment = Node(t->toAttached, t->attached);
  899.  
  900.     attachment->Exclude(t->dangling);
  901.     degen = OtherNode(t->dangling, attachment);
  902.     Delete(degen);
  903.     delete degen;
  904. }
  905.  
  906. void TNodeList::RemoveSeries (TElement* equiv, TElement* e1, TElement* e2) {
  907.     TNode* n1lb, *n2lb, *n2rt;
  908.     TNode eqlb(BottomLeft, equiv);
  909.     TNode eqrt(TopRight, equiv);
  910.     
  911.     Nodes(e2, n2lb, n2rt);
  912.     n1lb = OtherNode(e1, n2lb);
  913.     if (n1lb == nil) {            // check for ends tied together
  914.     n1lb = n2rt;
  915.     } else if (n2rt == nil) {
  916.     n2rt = n1lb;
  917.     }
  918.     n1lb->Merge(&eqlb);
  919.     n2rt->Merge(&eqrt);
  920.     n1lb->Exclude(e1);
  921.     n2rt->Exclude(e2);
  922.     Delete(n2lb);
  923.     delete n2lb;
  924. }
  925.  
  926. void TNodeList::Reverse (TElement* e) {
  927.     TNode* nlb, *nrt;
  928.     TNode elb(BottomLeft, e);
  929.     TNode ert(TopRight, e);
  930.     
  931.     Nodes(e, nlb, nrt);
  932.     nlb->Exclude(e);
  933.     nrt->Exclude(e);
  934.     nlb->Merge(&ert);
  935.     nrt->Merge(&elb);
  936.     e->Reverse();
  937. }
  938.  
  939. void TNodeList::RemoveParallel (TElement* equiv, TElement* e1, TElement* e2) {
  940.     TNode* n1lb, *n1rt;
  941.     TNode eqlb(BottomLeft, equiv);
  942.     TNode eqrt(TopRight, equiv);
  943.     
  944.     Nodes(e1, n1lb, n1rt);
  945.     n1lb->Merge(&eqlb);
  946.     n1rt->Merge(&eqrt);
  947.     n1lb->Exclude(e1);
  948.     n1lb->Exclude(e2);
  949.     n1rt->Exclude(e1);
  950.     n1rt->Exclude(e2);
  951. }
  952.  
  953. void TNodeList::RemoveLoop (TLoop* l) {
  954.     TNode* attachment;
  955.     
  956.     if (l->attached == nil) {            // isolated loop
  957.     attachment = OtherNode(l->looped, nil);
  958.     Delete(attachment);
  959.     delete attachment;
  960.     } else {
  961.     attachment = Node(l->toAttached, l->attached);
  962.     attachment->Exclude(l->looped);
  963.     }
  964. }
  965.  
  966. void TNodeList::ReplaceTermination (TTermination* t) {
  967.     TNode* degen, *attachment = Node(t->toAttached, t->attached);
  968.     float apos;
  969.  
  970.     Alignment a = Inverse(t->alignment);
  971.     TElement* e = t->dangling;
  972.     TNode temp(a, e);
  973.     attachment->Merge(&temp);
  974.     apos = attachment->GetPosition();
  975.     degen = new TNode(t->alignment, t->dangling);
  976.  
  977.     if (t->alignment == BottomLeft) {
  978.     degen->SetPosition(apos - t->dangling->nat - t->dangling->sigma);
  979.     } else {
  980.     degen->SetPosition(apos + t->dangling->nat + t->dangling->sigma);
  981.     }
  982.     Append(new TNodeList(degen));
  983. }
  984.  
  985. void TNodeList::ReplaceSeries (TElement* equiv, TElement* e1, TElement* e2) {
  986.     TNode* eqlb, *eqrt, *nctr;
  987.     
  988.     Nodes(equiv, eqlb, eqrt);
  989.     if (eqlb == nil) {            // check for ends tied together
  990.     eqlb = eqrt;
  991.     } else if (eqrt == nil) {
  992.     eqrt = eqlb;
  993.     }
  994.     TNode nlb(BottomLeft, e1);
  995.     TNode nrt(TopRight, e2);
  996.     eqlb->Merge(&nlb);
  997.     eqrt->Merge(&nrt);
  998.     eqlb->Exclude(equiv);
  999.     eqrt->Exclude(equiv);
  1000.     nctr = new TNode(TopRight, e1, BottomLeft, e2);
  1001.     nctr->SetPosition(e2->pos);
  1002.     Append(new TNodeList(nctr));
  1003. }
  1004.  
  1005. void TNodeList::ReplaceParallel (
  1006.     TElement* equiv, TElement* e1, TElement* e2
  1007. ) {
  1008.     TNode* eqlb, *eqrt;
  1009.     TNode nlb(BottomLeft, e1, BottomLeft, e2);
  1010.     TNode nrt(TopRight, e1, TopRight, e2);
  1011.     
  1012.     Nodes(equiv, eqlb, eqrt);
  1013.     eqlb->Merge(&nlb);
  1014.     eqrt->Merge(&nrt);
  1015.     eqlb->Exclude(equiv);
  1016.     eqrt->Exclude(equiv);
  1017. }
  1018.  
  1019. void TNodeList::ReplaceLoop (TLoop* l) {
  1020.     TNode* attachment;
  1021.     
  1022.     if (l->attached == nil) {
  1023.     attachment = new TNode(BottomLeft, l->looped, TopRight, l->looped);
  1024.     Append(new TNodeList(attachment));
  1025.  
  1026.     } else {
  1027.     attachment = Node(l->toAttached, l->attached);
  1028.     TNode node(BottomLeft, l->looped, TopRight, l->looped);
  1029.     attachment->Merge(&node);
  1030.     }
  1031. }
  1032.  
  1033. void TNodeList::FindElements (
  1034.     Interactor* i, TElement*& lbElem, TElement*& rtElem
  1035. ) {
  1036.     register TNodeList* nl;
  1037.     TNode* node;
  1038.     TElementList* el;
  1039.  
  1040.     lbElem = rtElem = nil;
  1041.     
  1042.     for (
  1043.     nl = First(); 
  1044.     nl != End() && (lbElem == nil || rtElem == nil);
  1045.     nl = nl->Next()
  1046.     ) {
  1047.     node = nl->GetNode();
  1048.     el = node->LeftBottomElements();
  1049.     FindElements(el, i, lbElem, rtElem);
  1050.  
  1051.     if (lbElem == nil || rtElem == nil) {
  1052.         el = node->RightTopElements();
  1053.         FindElements(el, i, lbElem, rtElem);
  1054.     }
  1055.     }
  1056. }        
  1057.  
  1058. void TNodeList::FindElement (TGlue* tg, TElement*& elem) {
  1059.     register TNodeList* nl;
  1060.     TNode* node;
  1061.     TElementList* el;
  1062.  
  1063.     elem = nil;
  1064.     
  1065.     for (nl = First(); nl != End() && elem == nil; nl = nl->Next()) {
  1066.     node = nl->GetNode();
  1067.     el = node->LeftBottomElements();
  1068.     FindElement(el, tg, elem);
  1069.  
  1070.     if (elem == nil) {
  1071.         el = node->RightTopElements();
  1072.         FindElement(el, tg, elem);
  1073.     }
  1074.     }
  1075. }        
  1076.  
  1077. void TNodeList::FindElements (
  1078.     TElementList* el, Interactor* i, TElement*& lbElem, TElement*& rtElem
  1079. ) {
  1080.     register TElementList* cur;
  1081.     TElement* test;
  1082.  
  1083.     for (
  1084.     cur = el->First(); 
  1085.     cur != el->End() && (lbElem == nil || rtElem == nil);
  1086.     cur = cur->Next()
  1087.     ) {
  1088.     test = cur->GetElem();
  1089.     if (test->owner == i) {
  1090.         if (test->leftBotHalf) {
  1091.         lbElem = test;
  1092.         } else {
  1093.         rtElem = test;
  1094.         }
  1095.     }
  1096.     }
  1097. }
  1098.  
  1099. void TNodeList::FindElement (TElementList* el, TGlue* tg, TElement*& elem) {
  1100.     register TElementList* cur;
  1101.     TElement* test;
  1102.  
  1103.     for (cur = el->First(); cur != el->End(); cur = cur->Next()) {
  1104.     test = cur->GetElem();
  1105.     if (test->tglue == tg) {
  1106.         elem = test;
  1107.         return;
  1108.     }
  1109.     }
  1110. }
  1111.  
  1112. void TNodeList::Nodes (TElement* e, TNode*& nlb, TNode*& nrt) {
  1113.     register TNodeList* t;
  1114.     TNode* node;
  1115.     Alignment a;
  1116.     
  1117.     nlb = nrt = nil;
  1118.     for (t = First(); t != End() && (nlb==nil || nrt==nil); t = t->Next()) {
  1119.     node = t->GetNode();
  1120.     if (node->Includes(a, e)) {
  1121.         if (a == BottomLeft) {    /* node is below/left of element */
  1122.         nlb = node;
  1123.         } else {
  1124.         nrt = node;
  1125.         }
  1126.     }
  1127.     }
  1128. }
  1129.  
  1130. TNode* TNodeList::Node (Alignment a, TElement* e) {
  1131.     register TNodeList* t;
  1132.     TNode* node;
  1133.     Alignment test;
  1134.     
  1135.     for (t = First(); t != End(); t = t->Next()) {
  1136.     node = t->GetNode();
  1137.     if (node->Includes(test, e) && test == a) {
  1138.         return node;
  1139.     }
  1140.     }
  1141. }
  1142.  
  1143. void TNodeList::AddMissingNodes (TElement* e) {
  1144.     TNode* nlb, *nrt;
  1145.     TNodeList* lb, *rt;
  1146.     
  1147.     Nodes(e, nlb, nrt);
  1148.     if (nlb == nil) {
  1149.     nlb = new TNode(BottomLeft, e);
  1150.     nlb->SetPosition(e->pos);
  1151.     lb = new TNodeList(nlb);
  1152.     Append(lb);
  1153.  
  1154.     } 
  1155.     if (nrt == nil) {
  1156.     nrt = new TNode(TopRight, e);
  1157.     nrt->SetPosition(e->pos + e->nat + e->sigma);
  1158.     rt = new TNodeList(nrt);
  1159.     Append(rt);
  1160.     }
  1161. }
  1162.  
  1163. void TNodeList::GetElemOtherThan (
  1164.     TElement* avoid, TNode* n, Alignment& a, TElement*& e
  1165. ) {
  1166.     register TElementList* cur;
  1167.     TElementList* lbElems, *rtElems;
  1168.     
  1169.     lbElems = n->LeftBottomElements();
  1170.     rtElems = n->RightTopElements();
  1171.     
  1172.     for (cur = lbElems->First(); cur != lbElems->End(); cur = cur->Next()) {
  1173.     e = cur->GetElem();
  1174.     if (e != avoid) {
  1175.         a = TopRight;
  1176.         return;
  1177.     }
  1178.     }
  1179.     for (cur = rtElems->First(); cur != rtElems->End(); cur = cur->Next()) {
  1180.     e = cur->GetElem();
  1181.     if (e != avoid) {
  1182.         a = BottomLeft;
  1183.         return;
  1184.     }
  1185.     }
  1186.     e = nil;
  1187. }
  1188.  
  1189. void TNodeList::ApplyToTermination (TTermination* t) {
  1190.     TNode* n = Node(t->toAttached, t->attached);
  1191.  
  1192.     if (t->alignment == BottomLeft) {
  1193.     t->dangling->pos = n->GetPosition() - t->dangling->nat;
  1194.  
  1195.     } else {
  1196.     t->dangling->pos = n->GetPosition();
  1197.  
  1198.     }
  1199.     t->dangling->sigma = 0;
  1200. }
  1201.  
  1202. void TNodeList::ApplyToSeries (TElement* equiv, TElement* e1, TElement* e2) {
  1203.     float d = equiv->nat + equiv->sigma - e1->nat - e2->nat;
  1204.     float s1, s2;
  1205.     
  1206.     if (d < 0) {
  1207.     s1 = e1->shrink;
  1208.     s2 = e2->shrink;
  1209.     } else {
  1210.     s1 = e1->stretch;
  1211.     s2 = e2->stretch;
  1212.     }
  1213.     if (s1 == 0 && s2 == 0) {
  1214.     e1->sigma = e2->sigma = 0;
  1215.     } else {
  1216.     e1->sigma = equiv->sigma * s1 / (s1 + s2);
  1217.     }
  1218.  
  1219.     e1->Limit();
  1220.     e2->sigma = equiv->sigma - e1->sigma;
  1221.     e2->Limit();
  1222.     e1->pos = equiv->pos;
  1223.     e2->pos = e1->pos + e1->nat + e1->sigma;
  1224. }
  1225.  
  1226. void TNodeList::ApplyToParallel (TElement* equiv, TElement* e1, TElement* e2) {
  1227.     e1->pos = e2->pos = equiv->pos;
  1228.     e1->sigma = equiv->nat + equiv->sigma - e1->nat;
  1229.     e2->sigma = equiv->nat + equiv->sigma - e2->nat;
  1230.     e1->Limit();
  1231.     e2->Limit();
  1232. }
  1233.  
  1234. void TNodeList::ApplyToLoop (TLoop* l) {
  1235.     TNode* n = Node(l->toAttached, l->attached);
  1236.  
  1237.     l->looped->pos = n->GetPosition();
  1238.     l->looped->sigma = -l->looped->shrink;
  1239. }
  1240.  
  1241. /*************************************************************************/
  1242.  
  1243. class TSolver {
  1244. public:
  1245.     TSolver(Tray*, Interactor*);
  1246.     ~TSolver();
  1247.  
  1248.     void AddAlignment(Alignment, Interactor*, TGlue* = nil);
  1249.     void AddAlignment(
  1250.     Alignment, Interactor*, Alignment, Interactor*, TGlue* = nil
  1251.     );
  1252.     void DeleteAlignmentsTo(Interactor*);
  1253.     void SetShape(Interactor*);
  1254.     void Solve(int, int);
  1255.     void CalcShape(Shape*);
  1256.     void GetPlacement(Interactor*, Coord&, Coord&, Coord&, Coord&);
  1257. private:
  1258.     TNodeList* hnodes, *vnodes;
  1259.     TNode* lmagic, *rmagic, *bmagic, *tmagic;
  1260.     Tray* tray;
  1261.     Interactor* background;
  1262.  
  1263.     Interactor* BgFilter(Interactor*);
  1264.     void Solve(
  1265.     TNodeList*, TNode*, TNode*, int size, int& nat, int& shr, int& str
  1266.     );
  1267.     void GetPlacement(TNodeList*, Interactor*, int, Coord&, Coord&);
  1268.  
  1269.     void HOrder(Alignment, Interactor*&, Interactor*&);
  1270.     void VOrder(Alignment, Interactor*&, Interactor*&);
  1271.     void HConvert(Interactor*, TElement*&, TElement*&);
  1272.     void HConvert(TGlue*, TElement*&);
  1273.     void VConvert(Interactor*, TElement*&, TElement*&);
  1274.     void VConvert(TGlue*, TElement*&);
  1275.     void HAddAlignment(
  1276.     Alignment, TElement*, TElement*, Alignment, TElement*, TElement*,
  1277.     TElement*
  1278.     );
  1279.     void VAddAlignment(
  1280.     Alignment, TElement*, TElement*, Alignment, TElement*, TElement*,
  1281.     TElement*
  1282.     );
  1283.     void Include(
  1284.     TNodeList*, Alignment, TElement*, Alignment, TElement*, TElement*
  1285.     );
  1286.     void TrayNodes(TNodeList*, TNode*&, TNode*&);
  1287.     void UpdateMagicNodes();
  1288.     void DeleteDanglingGlue(TNodeList*, TNode*);
  1289.     void DeleteNodesAndElements(TNodeList*);
  1290. };
  1291.  
  1292. TSolver::TSolver (Tray* t, Interactor* bg) {
  1293.     hnodes = new TNodeList;
  1294.     vnodes = new TNodeList;
  1295.     tray = t;
  1296.     background = bg;
  1297.     lmagic = rmagic = bmagic = tmagic = nil;
  1298. }
  1299.  
  1300. TSolver::~TSolver () {
  1301.     DeleteNodesAndElements(hnodes);
  1302.     DeleteNodesAndElements(vnodes);
  1303.     delete hnodes;
  1304.     delete vnodes;
  1305. }
  1306.  
  1307. void TSolver::DeleteNodesAndElements (TNodeList* nodes) {
  1308.     TNode* merged;
  1309.     register TNodeList* t = nodes->First();
  1310.     
  1311.     if (t == nodes->End()) {
  1312.         return;
  1313.     }
  1314.     merged = t->GetNode();
  1315.  
  1316.     for (t = t->Next(); t != nodes->End(); t = t->Next()) {
  1317.         TNode* doomed = t->GetNode();
  1318.         merged->Merge(doomed);
  1319.         delete doomed;
  1320.     }
  1321.     merged->DeleteElements();
  1322.     delete merged;
  1323. }
  1324.  
  1325. inline boolean HAlignment (Alignment a) {
  1326.     return a != Bottom && a != VertCenter && a != Top;
  1327. }
  1328.  
  1329. inline boolean VAlignment (Alignment a) {
  1330.     return a != Left && a != HorizCenter && a != Right;
  1331. }
  1332.  
  1333. void TSolver::AddAlignment (
  1334.     Alignment a1, Interactor* i1, Alignment a2, Interactor* i2, TGlue* tg
  1335. ) {
  1336.     TElement* e1l, *e1r, *e2l, *e2r, *e3;
  1337.     
  1338.     i1 = BgFilter(i1);
  1339.     i2 = BgFilter(i2);
  1340.     
  1341.     if (HAlignment(a1) && HAlignment(a2)) {
  1342.     HConvert(i1, e1l, e1r);
  1343.     HConvert(i2, e2l, e2r);
  1344.     HConvert(tg, e3);
  1345.     HAddAlignment(a1, e1l, e1r, a2, e2l, e2r, e3);
  1346.     }
  1347.  
  1348.     if (VAlignment(a1) && VAlignment(a2)) {
  1349.     VConvert(i1, e1l, e1r);
  1350.     VConvert(i2, e2l, e2r);
  1351.     VConvert(tg, e3);
  1352.     VAddAlignment(a1, e1l, e1r, a2, e2l, e2r, e3);
  1353.     }
  1354.     UpdateMagicNodes();
  1355. }
  1356.  
  1357. void TSolver::AddAlignment (Alignment a, Interactor* i, TGlue* tg) {
  1358.     TElement* e1l, *e1r, *e2l, *e2r, *e3;
  1359.     Interactor* i1 = i;
  1360.     Interactor* i2 = tray;
  1361.     
  1362.     if (i == background || i == tray) {
  1363.     return;
  1364.     }
  1365.  
  1366.     if (HAlignment(a)) {
  1367.     HOrder(a, i1, i2);
  1368.     HConvert(i1, e1l, e1r);
  1369.     HConvert(i2, e2l, e2r);
  1370.     HConvert(tg, e3);
  1371.     HAddAlignment(a, e1l, e1r, a, e2l, e2r, e3);
  1372.     }
  1373.  
  1374.     if (VAlignment(a)) {
  1375.     VOrder(a, i1, i2);
  1376.     VConvert(i1, e1l, e1r);
  1377.     VConvert(i2, e2l, e2r);
  1378.     VConvert(tg, e3);
  1379.     VAddAlignment(a, e1l, e1r, a, e2l, e2r, e3);
  1380.     }
  1381.     UpdateMagicNodes();
  1382. }
  1383.  
  1384. void TSolver::HOrder (Alignment a, Interactor*& i1, Interactor*& i2) {
  1385.     Interactor* i = (i1 == tray) ? i2 : i1;
  1386.     
  1387.     if (a == BottomRight || a == CenterRight || a == TopRight || a == Right) {
  1388.     i1 = i;
  1389.     i2 = tray;
  1390.     } else {
  1391.     i1 = tray;
  1392.     i2 = i;
  1393.     }
  1394. }
  1395.  
  1396. void TSolver::VOrder (Alignment a, Interactor*& i1, Interactor*& i2) {
  1397.     Interactor* i = (i1 == tray) ? i2 : i1;
  1398.     
  1399.     if (a == TopLeft || a == TopCenter || a == TopRight || a == Top) {
  1400.     i1 = i;
  1401.     i2 = tray;
  1402.     } else {
  1403.     i1 = tray;
  1404.     i2 = i;
  1405.     }
  1406. }
  1407.  
  1408. void TSolver::DeleteAlignmentsTo (Interactor* i) {
  1409.     TElement* e1, *e2;
  1410.     TNode* lb, *rt;
  1411.  
  1412.     i = BgFilter(i);
  1413.     hnodes->FindElements(i, e1, e2);
  1414.  
  1415.     if (e1 != nil) {
  1416.         lb = hnodes->Node(BottomLeft, e1);
  1417.         rt = hnodes->Node(TopRight, e2);
  1418.         hnodes->Exclude(e1);
  1419.         hnodes->Exclude(e2);
  1420.         delete e1;
  1421.         delete e2;
  1422.         DeleteDanglingGlue(hnodes, lb);
  1423.         DeleteDanglingGlue(hnodes, rt);
  1424.     }
  1425.  
  1426.     vnodes->FindElements(i, e1, e2);
  1427.  
  1428.     if (e1 != nil) {
  1429.         lb = vnodes->Node(BottomLeft, e1);
  1430.         rt = vnodes->Node(TopRight, e2);
  1431.         vnodes->Exclude(e1);
  1432.         vnodes->Exclude(e2);
  1433.         delete e1;
  1434.         delete e2;
  1435.         DeleteDanglingGlue(vnodes, lb);
  1436.         DeleteDanglingGlue(vnodes, rt);
  1437.     }
  1438. }
  1439.  
  1440. void TSolver::SetShape (Interactor* i) {
  1441.     TElement* lbElem, *rtElem;
  1442.  
  1443.     i = BgFilter(i);
  1444.  
  1445.     hnodes->FindElements(i, lbElem, rtElem);
  1446.     if (lbElem == nil) {
  1447.     return;
  1448.     }
  1449.     lbElem->HSetShape();
  1450.     rtElem->HSetShape();
  1451.  
  1452.     vnodes->FindElements(i, lbElem, rtElem);
  1453.     if (lbElem == nil) {
  1454.     return;
  1455.     }
  1456.     lbElem->VSetShape();
  1457.     rtElem->VSetShape();
  1458. }
  1459.  
  1460. void TSolver::Solve (int w, int h) {
  1461.     int dummy;
  1462.  
  1463.     if (lmagic != nil) {
  1464.         lmagic->SetPosition(0);
  1465.         rmagic->SetPosition(w);
  1466.         Solve(hnodes, lmagic, rmagic, w, dummy, dummy, dummy);
  1467.     }
  1468.     if (bmagic != nil) {
  1469.         bmagic->SetPosition(0);
  1470.         tmagic->SetPosition(h);
  1471.         Solve(vnodes, bmagic, tmagic, h, dummy, dummy, dummy);
  1472.     }
  1473. }
  1474.  
  1475. void TSolver::CalcShape (Shape* s) {
  1476.     TElement* ltray, *rtray, *btray, *ttray;
  1477.     
  1478.     hnodes->FindElements(tray, ltray, rtray);
  1479.     vnodes->FindElements(tray, btray, ttray);
  1480.  
  1481.     if (ltray != nil && lmagic != nil) {
  1482.         ltray->combinable = rtray->combinable = false;
  1483.         Solve(hnodes, lmagic, rmagic, 0, s->width, s->hshrink, s->hstretch);
  1484.         ltray->combinable = rtray->combinable = true;
  1485.     }
  1486.  
  1487.     if (btray != nil && bmagic != nil) {
  1488.         btray->combinable = ttray->combinable = false;
  1489.         Solve(vnodes, bmagic, tmagic, 0, s->height, s->vshrink, s->vstretch);
  1490.         btray->combinable = ttray->combinable = true;
  1491.     }
  1492. }
  1493.  
  1494. void TSolver::GetPlacement (
  1495.     Interactor* i, Coord& l, Coord& b, Coord& r, Coord& t
  1496. ) {
  1497.     Shape* s = i->GetShape();
  1498.  
  1499.     GetPlacement(hnodes, i, s->width, l, r);
  1500.     GetPlacement(vnodes, i, s->height, b, t);
  1501. }
  1502.  
  1503. void TSolver::GetPlacement (
  1504.     TNodeList* nodes, Interactor* i, int dfault, Coord& lb, Coord& rt
  1505. ) {
  1506.     TElement* lbElem, *rtElem;
  1507.  
  1508.     nodes->FindElements(i, lbElem, rtElem);
  1509.     if (lbElem == nil) {
  1510.     lb = 0;
  1511.     rt = dfault - 1;
  1512.     } else {
  1513.     lb = round(lbElem->pos);
  1514.     rt = round(
  1515.         lbElem->pos + lbElem->nat + lbElem->sigma +
  1516.         rtElem->nat + rtElem->sigma - 1
  1517.     );
  1518.     }
  1519. }
  1520.  
  1521. void TSolver::Solve (
  1522.     TNodeList* nodes, TNode* lbMagic, TNode* rtMagic, int size,
  1523.     int& nat, int& shr, int& str
  1524. ) {
  1525.     TElement* e1, *e2, *e3;
  1526.     TTermination* t;
  1527.     TLoop* l;
  1528.     TNode* n;
  1529.     
  1530.     if (nodes->Empty()) {
  1531.     /* no alignments; do nothing */
  1532.     
  1533.     } else if (nodes->Degenerate(e1)) {
  1534.     nat = round(e1->nat);
  1535.     shr = round(e1->shrink);
  1536.     str = round(e1->stretch);
  1537.     e1->pos = (lbMagic == nil) ? 0 : lbMagic->GetPosition();
  1538.     e1->sigma = (rtMagic == nil) ? e1->nat : size - round(e1->nat);
  1539.     e1->Limit();
  1540.  
  1541.     } else if (nodes->FoundSeries(e1, e2, lbMagic, rtMagic)) {
  1542.     e3 = e1->Series(e2);
  1543.     nodes->RemoveSeries(e3, e1, e2);
  1544.     Solve(nodes, lbMagic, rtMagic, size, nat, shr, str);
  1545.     nodes->ApplyToSeries(e3, e1, e2);
  1546.     nodes->ReplaceSeries(e3, e1, e2);
  1547.     delete e3;
  1548.  
  1549.     } else if (nodes->FoundParallel(e1, e2)) {
  1550.     e3 = e1->Parallel(e2);
  1551.     nodes->RemoveParallel(e3, e1, e2);
  1552.     Solve(nodes, lbMagic, rtMagic, size, nat, shr, str);
  1553.     nodes->ApplyToParallel(e3, e1, e2);
  1554.     nodes->ReplaceParallel(e3, e1, e2);
  1555.     delete e3;
  1556.  
  1557.     } else if (nodes->FoundTermination(t, lbMagic, rtMagic)) {
  1558.     nodes->RemoveTermination(t);
  1559.     Solve(nodes, lbMagic, rtMagic, size, nat, shr, str);
  1560.     nodes->ApplyToTermination(t);
  1561.     nodes->ReplaceTermination(t);
  1562.     delete t;
  1563.     
  1564.     } else if (nodes->FoundStub(e1) || nodes->FoundCrossover(e1)) {
  1565.     nodes->Reverse(e1);
  1566.     Solve(nodes, lbMagic, rtMagic, size, nat, shr, str);
  1567.     nodes->Reverse(e1);
  1568.  
  1569.     } else if (nodes->FoundLoop(l)) {
  1570.     nodes->RemoveLoop(l);
  1571.     Solve(nodes, lbMagic, rtMagic, size, nat, shr, str);
  1572.     nodes->ApplyToLoop(l);
  1573.     nodes->ReplaceLoop(l);
  1574.     delete l;
  1575.  
  1576.     } else if (nodes->OnlyOne()) {
  1577.     n = nodes->First()->GetNode();
  1578.     if (n != lbMagic && n != rtMagic) {
  1579.         n->SetPosition(0);
  1580.     }
  1581.     nat = str = shr = 0;
  1582.     }
  1583. }
  1584.  
  1585. void TSolver::HConvert (Interactor* i, TElement*& el, TElement*& er) {
  1586.     if (i == nil) {
  1587.     el = er = nil;
  1588.  
  1589.     } else {
  1590.     hnodes->FindElements(i, el, er);
  1591.     if (el == nil) {
  1592.         el = new TElement(i);
  1593.         el->combinable = true;
  1594.         el->leftBotHalf = true;
  1595.         el->HSetShape();
  1596.     
  1597.         er = new TElement(i);
  1598.         er->combinable = true;
  1599.         er->leftBotHalf = false;
  1600.         er->HSetShape();
  1601.         hnodes->Include(TopRight, el, BottomLeft, er);
  1602.     }
  1603.     }
  1604. }
  1605.  
  1606. void TSolver::HConvert (TGlue* tg, TElement*& e) {
  1607.     if (tg == nil) {
  1608.     e = nil;
  1609.  
  1610.     } else {
  1611.     hnodes->FindElement(tg, e);
  1612.     if (e == nil) {
  1613.         e = new TElement(tg);
  1614.         e->combinable = true;
  1615.         e->leftBotHalf = true;
  1616.         e->HSetShape();
  1617.     }
  1618.     }
  1619. }
  1620.  
  1621. void TSolver::VConvert (Interactor* i, TElement*& eb, TElement*& et) {
  1622.     if (i == nil) {
  1623.     eb = et = nil;
  1624.  
  1625.     } else {
  1626.     vnodes->FindElements(i, eb, et);
  1627.     if (eb == nil) {
  1628.         eb = new TElement(i);
  1629.         eb->combinable = true;
  1630.         eb->leftBotHalf = true;
  1631.         eb->VSetShape();
  1632.     
  1633.         et = new TElement(i);
  1634.         et->combinable = true;
  1635.         et->leftBotHalf = false;
  1636.         et->VSetShape();
  1637.         vnodes->Include(TopRight, eb, BottomLeft, et);
  1638.     }
  1639.     }
  1640. }
  1641.  
  1642. void TSolver::VConvert (TGlue* tg, TElement*& e) {
  1643.     if (tg == nil) {
  1644.     e = nil;
  1645.  
  1646.     } else {
  1647.     vnodes->FindElement(tg, e);
  1648.     if (e == nil) {
  1649.         e = new TElement(tg);
  1650.         e->combinable = true;
  1651.         e->leftBotHalf = true;
  1652.         e->VSetShape();
  1653.     }
  1654.     }
  1655. }
  1656.  
  1657. void TSolver::HAddAlignment (
  1658.     Alignment a1, TElement* e1l, TElement* e1r,
  1659.     Alignment a2, TElement* e2l, TElement* e2r,
  1660.     TElement* tg
  1661. ) {
  1662.     TElement* e1, *e2;
  1663.     Alignment na1, na2;
  1664.     
  1665.     switch (a1) {
  1666.     case TopLeft:
  1667.     case CenterLeft:
  1668.     case BottomLeft:
  1669.     case Left:
  1670.         e1 = e1l;
  1671.         na1 = BottomLeft;
  1672.         break;
  1673.     case TopCenter:
  1674.     case Center:
  1675.     case BottomCenter:
  1676.     case HorizCenter:
  1677.         e1 = e1l;
  1678.         na1 = TopRight;
  1679.         break;
  1680.     case TopRight:
  1681.     case CenterRight:
  1682.     case BottomRight:
  1683.     case Right:
  1684.         e1 = e1r;
  1685.         na1 = TopRight;
  1686.         break;
  1687.     }
  1688.     switch (a2) {
  1689.     case TopLeft:
  1690.     case CenterLeft:
  1691.     case BottomLeft:
  1692.     case Left:
  1693.         e2 = e2l;
  1694.         na2 = BottomLeft;
  1695.         break;
  1696.     case TopCenter:
  1697.     case Center:
  1698.     case BottomCenter:
  1699.     case HorizCenter:
  1700.         e2 = e2l;
  1701.         na2 = TopRight;
  1702.         break;
  1703.     case TopRight:
  1704.     case CenterRight:
  1705.     case BottomRight:
  1706.     case Right:
  1707.         e2 = e2r;
  1708.         na2 = TopRight;
  1709.         break;
  1710.     }
  1711.     hnodes->AddMissingNodes(e1l);
  1712.     hnodes->AddMissingNodes(e1r);
  1713.     hnodes->AddMissingNodes(e2l);
  1714.     hnodes->AddMissingNodes(e2r);
  1715.     Include(hnodes, na1, e1, na2, e2, tg);
  1716. }
  1717.  
  1718. void TSolver::VAddAlignment (
  1719.     Alignment a1, TElement* e1b, TElement* e1t,
  1720.     Alignment a2, TElement* e2b, TElement* e2t,
  1721.     TElement* tg
  1722. ) {
  1723.     TElement* e1, *e2;
  1724.     Alignment na1, na2;
  1725.     
  1726.     switch (a1) {
  1727.     case BottomLeft:
  1728.     case BottomCenter:
  1729.     case BottomRight:
  1730.     case Bottom:
  1731.         e1 = e1b;
  1732.         na1 = BottomLeft;
  1733.         break;
  1734.     case CenterLeft:
  1735.     case Center:
  1736.     case CenterRight:
  1737.     case VertCenter:
  1738.         e1 = e1b;
  1739.         na1 = TopRight;
  1740.         break;
  1741.     case TopLeft:
  1742.     case TopCenter:
  1743.     case TopRight:
  1744.     case Top:
  1745.         e1 = e1t;
  1746.         na1 = TopRight;
  1747.         break;
  1748.     }
  1749.     switch (a2) {
  1750.     case BottomLeft:
  1751.     case BottomCenter:
  1752.     case BottomRight:
  1753.     case Bottom:
  1754.         e2 = e2b;
  1755.         na2 = BottomLeft;
  1756.         break;
  1757.     case CenterLeft:
  1758.     case Center:
  1759.     case CenterRight:
  1760.     case VertCenter:
  1761.         e2 = e2b;
  1762.         na2 = TopRight;
  1763.         break;
  1764.     case TopLeft:
  1765.     case TopCenter:
  1766.     case TopRight:
  1767.     case Top:
  1768.         e2 = e2t;
  1769.         na2 = TopRight;
  1770.         break;
  1771.     }
  1772.     vnodes->AddMissingNodes(e1b);
  1773.     vnodes->AddMissingNodes(e1t);
  1774.     vnodes->AddMissingNodes(e2b);
  1775.     vnodes->AddMissingNodes(e2t);
  1776.     Include(vnodes, na1, e1, na2, e2, tg);
  1777. }
  1778.  
  1779. void TSolver::Include (
  1780.     TNodeList* nodes, 
  1781.     Alignment na1, TElement* e1, Alignment na2, TElement* e2, TElement* tg
  1782. ) {
  1783.     if (e1->owner == e2->owner && na1 == na2) {
  1784.     /* aligned a node to itself; do nothing */
  1785.     
  1786.     } else if (tg == nil) {
  1787.     nodes->Include(na1, e1, na2, e2);
  1788.  
  1789.     } else if (na1 == BottomLeft && na2 == TopRight) {
  1790.     nodes->Include(BottomLeft, e1, TopRight, tg);
  1791.     nodes->Include(TopRight, e2, BottomLeft, tg);
  1792.  
  1793.     } else {
  1794.     nodes->Include(na1, e1, BottomLeft, tg);
  1795.     nodes->Include(na2, e2, TopRight, tg);
  1796.     }
  1797. }
  1798.  
  1799. void TSolver::TrayNodes (TNodeList* nodes, TNode*& nlb, TNode*& nrt) {
  1800.     TNode *ctr;
  1801.     TElement* elb, *ert;
  1802.  
  1803.     nodes->FindElements(tray, elb, ert);
  1804.     if (elb == nil) {
  1805.     nlb = nrt = nil;
  1806.     } else {
  1807.     nodes->Nodes(elb, nlb, ctr);
  1808.     nrt = nodes->OtherNode(ert, ctr);
  1809.     }
  1810. }
  1811.  
  1812. void TSolver::UpdateMagicNodes () {
  1813.     TrayNodes(hnodes, lmagic, rmagic);
  1814.     TrayNodes(vnodes, bmagic, tmagic);
  1815. }
  1816.  
  1817. void TSolver::DeleteDanglingGlue (TNodeList* nodes, TNode* n) {
  1818.     TElement* e;
  1819.  
  1820.     if (n->Degenerate(e) && e->tglue != nil) {
  1821.         nodes->Exclude(e);
  1822.         delete e;
  1823.     }
  1824. }
  1825.  
  1826. Interactor* TSolver::BgFilter (Interactor* i) {
  1827.     return (i == background) ? tray : i;
  1828. }
  1829.  
  1830. /*************************************************************************/
  1831.  
  1832. class TrayElement {
  1833. public:
  1834.     Interactor* child;
  1835.     boolean visible;
  1836.     TrayElement* next;
  1837. };
  1838.  
  1839. /*************************************************************************/
  1840.  
  1841. TGlue::TGlue (int w, int h, int hstr, int vstr) {
  1842.     shape = new Shape;
  1843.     shape->width = w;
  1844.     shape->height = h;
  1845.     shape->hshrink = 0;
  1846.     shape->hstretch = hstr;
  1847.     shape->vshrink = 0;
  1848.     shape->vstretch = vstr;
  1849. }
  1850.  
  1851. TGlue::TGlue (int w, int h, int hshr, int hstr, int vshr, int vstr) {
  1852.     shape = new Shape;
  1853.     shape->width = w;
  1854.     shape->height = h;
  1855.     shape->hshrink = hshr;
  1856.     shape->hstretch = hstr;
  1857.     shape->vshrink = vshr;
  1858.     shape->vstretch = vstr;
  1859. }
  1860.  
  1861. TGlue::~TGlue () {
  1862.     delete shape;
  1863. }
  1864.  
  1865. /*************************************************************************/
  1866.  
  1867. inline boolean Tray::TrayOrBg (Interactor* i) { return i == this || i == bg; }
  1868.  
  1869. Tray::Tray (Interactor* b) {
  1870.     Init(b);
  1871. }
  1872.  
  1873. Tray::Tray (const char* name, Interactor* b) {
  1874.     SetInstance(name);
  1875.     Init(b);
  1876. }
  1877.  
  1878. void Tray::Init (Interactor* b) {
  1879.     SetClassName("Tray");
  1880.     nelements = 0;
  1881.     head = nil;
  1882.     tail = nil;
  1883.     bg = b;
  1884.     tsolver = new TSolver(this, bg);
  1885. }
  1886.  
  1887. Tray::~Tray () {
  1888.     register TrayElement* e, *next;
  1889.  
  1890.     delete tsolver;
  1891.  
  1892.     for (e = head; e != nil; e = next) {
  1893.         next = e->next;
  1894.         delete e->child;
  1895.     delete e;
  1896.     }
  1897.     if (bg != nil) {
  1898.     delete bg;
  1899.     }
  1900. }
  1901.  
  1902. void Tray::ComponentBounds (int& w, int& h) {
  1903.     register TrayElement* e, *next;
  1904.     Shape* s;
  1905.     
  1906.     w = h = 0;
  1907.     for (e = head; e != nil; e = next) {
  1908.         next = e->next;
  1909.         s = e->child->GetShape();
  1910.     w = max(w, s->width);
  1911.     h = max(h, s->height);
  1912.     }
  1913. }    
  1914.  
  1915. void Tray::CalcShape () {
  1916.     int w, h;
  1917.  
  1918.     if (bg == nil) {
  1919.     ComponentBounds(w, h);
  1920.     tsolver->CalcShape(shape);
  1921.     shape->width = max(shape->width, w);
  1922.     shape->height = max(shape->height, h);
  1923.     } else {
  1924.     *shape = *bg->GetShape();
  1925.     }
  1926.     tsolver->SetShape(this);
  1927. }
  1928.  
  1929. void Tray::Reconfig () {
  1930.     register TrayElement* e;
  1931.  
  1932.     for (e = head; e != nil; e = e->next) {
  1933.     tsolver->SetShape(e->child);
  1934.     }
  1935.     CalcShape();
  1936. }
  1937.  
  1938. void Tray::DoInsert (Interactor* i, boolean, Coord&, Coord&) {
  1939.     ++nelements;
  1940.     register TrayElement* e = new TrayElement;
  1941.     e->child = i;
  1942.     e->next = nil;
  1943.     if (head == nil) {
  1944.         head = e;
  1945.         tail = e;
  1946.     } else {
  1947.         tail->next = e;
  1948.         tail = e;
  1949.     }
  1950. }
  1951.  
  1952. void Tray::DoChange (Interactor* i) {
  1953.     tsolver->SetShape(i);
  1954.     CalcShape();
  1955. }
  1956.  
  1957. void Tray::DoRemove (Interactor* i) {
  1958.     register TrayElement* e, * prev;
  1959.  
  1960.     if (i == bg) {
  1961.     bg = nil;
  1962.     tsolver->DeleteAlignmentsTo(i);
  1963.     } else {
  1964.     --nelements;
  1965.     prev = nil;
  1966.     for (e = head; e != nil; e = e->next) {
  1967.         if (e->child == i) {
  1968.         if (prev == nil) {
  1969.             head = e->next;
  1970.         } else {
  1971.             prev->next = e->next;
  1972.         }
  1973.         if (e == tail) {
  1974.             tail = prev;
  1975.         }
  1976.         delete e;
  1977.         tsolver->DeleteAlignmentsTo(i);
  1978.         break;
  1979.         }
  1980.         prev = e;
  1981.     }
  1982.     }
  1983. }
  1984.  
  1985. void Tray::Resize () {
  1986.     register TrayElement* e;
  1987.  
  1988.     canvas->SetBackground(output->GetBgColor());
  1989.     if (bg != nil) {
  1990.     Place(bg, 0, 0, xmax, ymax);
  1991.     }
  1992.  
  1993.     for (e = head; e != nil; e = e->next) {
  1994.     tsolver->SetShape(e->child);
  1995.     }
  1996.  
  1997.     tsolver->Solve(xmax+1, ymax+1);
  1998.  
  1999.     for (e = head; e != nil; e = e->next) {
  2000.     PlaceElement(e);
  2001.     }
  2002. }
  2003.  
  2004. boolean Tray::AlreadyInserted (Interactor* i) {
  2005.     register TrayElement* e;
  2006.  
  2007.     if (i == this || i == bg) {
  2008.     return true;
  2009.     }
  2010.     
  2011.     for (e = head; e != nil; e = e->next) {
  2012.     if (e->child == i) {
  2013.         return true;
  2014.     }
  2015.     }
  2016.     return false;
  2017. }
  2018.  
  2019. void Tray::PlaceElement (TrayElement* e) {
  2020.     Coord l, b, r, t, tmp;
  2021.     tsolver->GetPlacement(e->child, l, b, r, t);
  2022.  
  2023.     if (
  2024.     r > 0 && l < xmax && t > 0 && b < ymax && 
  2025.     r - l != -1 && t - b != -1
  2026.     ) {
  2027.     e->visible = true;
  2028.     tmp = min(l, r);
  2029.     r = max(l, r);
  2030.     l = tmp;
  2031.     tmp = min(b, t);
  2032.     t = max(b, t);
  2033.     b = tmp;
  2034.     Place(e->child, l, b, r, t);
  2035.     } else {
  2036.     e->visible = false;
  2037.     }
  2038. }
  2039.  
  2040. void Tray::Draw () {
  2041.     register TrayElement* e;
  2042.  
  2043.     if (bg != nil) {
  2044.     bg->Draw();
  2045.     }
  2046.     for (e = head; e != nil; e = e->next) {
  2047.         if (e->visible) {
  2048.             e->child->Draw();
  2049.         }
  2050.     }
  2051. }
  2052.  
  2053. void Tray::Reshape (Shape& s) {
  2054.     *shape = s;
  2055.     Scene* p = Parent();
  2056.     if (p != nil) {
  2057.     p->Change(this);
  2058.     }
  2059. }
  2060.  
  2061. void Tray::GetComponents (Interactor** c, int nc, Interactor**& a, int& n) {
  2062.     register TrayElement* e;
  2063.     register Interactor** ap;
  2064.  
  2065.     n = nelements;
  2066.     if (bg != nil) {
  2067.     ++n;
  2068.     }
  2069.     a = (n <= nc) ? c : new Interactor*[n];
  2070.     ap = a;
  2071.     for (e = head; e != nil; e = e->next) {
  2072.         *ap++ = e->child;
  2073.     }
  2074.     if (bg != nil) {
  2075.     *ap = bg;
  2076.     }
  2077. }
  2078.  
  2079. void Tray::Align (
  2080.     Alignment a1, Interactor* i1, Alignment a2, Interactor* i2, TGlue* tg
  2081. ) {
  2082.     if (!AlreadyInserted(i1)) {
  2083.     Insert(i1);
  2084.     }
  2085.     if (!AlreadyInserted(i2)) {
  2086.     Insert(i2);
  2087.     }
  2088.     tsolver->AddAlignment(a1, i1, a2, i2, tg);
  2089. }
  2090.  
  2091. void Tray::Align (Alignment a, Interactor* i, TGlue* tg) {
  2092.     if (!AlreadyInserted(i)) {
  2093.     Insert(i);
  2094.     }
  2095.     tsolver->AddAlignment(a, i, tg);
  2096. }
  2097.  
  2098. static void LoadInteractorArray (
  2099.     Interactor* i[], Interactor* i0, Interactor* i1,
  2100.     Interactor* i2, Interactor* i3, Interactor* i4,
  2101.     Interactor* i5, Interactor* i6
  2102. ) {
  2103.     i[0] = i0;
  2104.     i[1] = i1;
  2105.     i[2] = i2;
  2106.     i[3] = i3;
  2107.     i[4] = i4;
  2108.     i[5] = i5;
  2109.     i[6] = i6;
  2110. }
  2111.  
  2112. void Tray::Align (
  2113.     Alignment a, Interactor* i0, Interactor* i1,
  2114.     Interactor* i2, Interactor* i3, Interactor* i4,
  2115.     Interactor* i5, Interactor* i6
  2116. ) {
  2117.     const int n = 7;
  2118.     Interactor* i[n];
  2119.     int k;
  2120.     
  2121.     LoadInteractorArray(i, i0, i1, i2, i3, i4, i5, i6);
  2122.     
  2123.     for (k = 0; k < n && i[k] != nil; ++k) {
  2124.     if (!AlreadyInserted(i[k])) {
  2125.         Insert(i[k]);
  2126.     }
  2127.     }
  2128.     for (k = 1; k < n && i[k] != nil; ++k) {
  2129.     tsolver->AddAlignment(a, i[k-1], a, i[k]);
  2130.     }    
  2131. }
  2132.  
  2133. void Tray::HBox (
  2134.     Interactor* i0, Interactor* i1,
  2135.     Interactor* i2, Interactor* i3, Interactor* i4,
  2136.     Interactor* i5, Interactor* i6
  2137. ) {
  2138.     const int n = 7;
  2139.     Interactor* i[n];
  2140.     int k, last = n - 1;
  2141.     
  2142.     LoadInteractorArray(i, i0, i1, i2, i3, i4, i5, i6);
  2143.     
  2144.     for (k = 0; k < n && i[k] != nil; ++k) {
  2145.     if (!AlreadyInserted(i[k])) {
  2146.         Insert(i[k]);
  2147.     }
  2148.     }
  2149.     for (k = 1; k < n && i[k] != nil; ++k) {
  2150.     if (TrayOrBg(i[0]) && k == 1) {
  2151.         tsolver->AddAlignment(Left, this, Left, i[1]);
  2152.  
  2153.     } else if (TrayOrBg(i[k]) && (k == last || i[k+1] == nil)) {
  2154.         tsolver->AddAlignment(Right, i[k-1], Right, this);
  2155.  
  2156.     } else {
  2157.         tsolver->AddAlignment(Right, i[k-1], Left, i[k]);
  2158.     }
  2159.     }    
  2160. }
  2161.  
  2162. void Tray::VBox (
  2163.     Interactor* i0, Interactor* i1,
  2164.     Interactor* i2, Interactor* i3, Interactor* i4,
  2165.     Interactor* i5, Interactor* i6
  2166. ) {
  2167.     const int n = 7;
  2168.     Interactor* i[n];
  2169.     int k, last = n - 1;
  2170.     
  2171.     LoadInteractorArray(i, i0, i1, i2, i3, i4, i5, i6);
  2172.     
  2173.     for (k = 0; k < n && i[k] != nil; ++k) {
  2174.     if (!AlreadyInserted(i[k])) {
  2175.         Insert(i[k]);
  2176.     }
  2177.     }
  2178.     for (k = 1; k < n && i[k] != nil; ++k) {
  2179.     if (TrayOrBg(i[0]) && k == 1) {
  2180.         tsolver->AddAlignment(Top, this, Top, i[1]);
  2181.  
  2182.     } else if (TrayOrBg(i[k]) && (k == last || i[k+1] == nil)) {
  2183.         tsolver->AddAlignment(Bottom, i[k-1], Bottom, this);
  2184.  
  2185.     } else {
  2186.         tsolver->AddAlignment(Bottom, i[k-1], Top, i[k]);
  2187.     }
  2188.     }    
  2189. }
  2190.